home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 April: Mac OS SDK / Dev.CD Apr 98 SDK2.toast / Development Kits (Disc 2) / QuickTime / Programming Stuff / Documentation / develop articles / develop Issue 12 / Time Bases / TimeBaseSimple / TimeBaseSimpleAux.p < prev   
Encoding:
Text File  |  1997-02-26  |  21.4 KB  |  857 lines  |  [TEXT/MPS ]

  1.  
  2. (* This procedure gathers all the info about the current movie's time base             *)
  3. (* routines that modify the state of the time base will keep this up to date         *)
  4. (* Important to note here is that duration is specified in movie scale units        *)
  5.  
  6. PROCEDURE InitTBRecord(moov: Movie);
  7. VAR    tb: TimeBase;
  8.         scale:    TimeScale;
  9.         startTimeValue,
  10.         stopTimeValue:    TimeValue;
  11.         clock:        ComponentInstance;
  12.         clockN:    StringHandle;
  13.         err:    OSErr;
  14.         cd: ComponentDescription;
  15.         
  16. BEGIN
  17.     clockN := StringHandle(NewHandle(256)); (* good length for string         *)
  18.     
  19.     tb := GetMovieTimeBase(gMoov);            (* get movie's time base        *)
  20.     scale := GetMovieTimeScale(gMoov);        (* and the scale                *)
  21.     clock:= GetTimeBaseMasterClock(tb);        (* instance of clock being used    *)
  22.     err := GetComponentInfo(Component(clock), cd, Handle(clockN), NIL, NIL); (* also takes instances *)
  23.     
  24.     WITH gTBState DO
  25.       BEGIN
  26.          tBase := tb;
  27.         gTBState.flags := GetTimeBaseFlags(tb);
  28.         rate := GetTimeBaseRate(tb);
  29.  
  30.         startTimeValue := GetTimeBaseStartTime(tb, scale, startTime);
  31.         stopTimeValue := GetTimeBaseStopTime(tb, scale, stopTime);
  32.         duration := stopTimeValue - startTimeValue;
  33.         IF clockN <> NIL THEN        (* have a name *)
  34.             BEGIN
  35.             clockName := clockN^^;
  36.          END;
  37.         moovScale := scale;
  38.       END;
  39.     DisposeHandle(Handle(clockN));
  40. END;
  41.  
  42. (* Changes the state of looping in the movie if needed.
  43. *)
  44. PROCEDURE SetTBLoop(newFlags: LONGINT);
  45. VAR        targetTB: TimeBase;
  46.  
  47. BEGIN
  48.     targetTB := gTBState.tBase;
  49.     SetTimeBaseFlags(targetTB, newFlags);
  50.     gTBState.flags := newFlags;
  51. END;
  52.  
  53. (*********** Auxiliary routines ********************************************************)
  54.  
  55. (* Loads in a resource of type RCT#, a list of rectangles and passes back
  56.    the rect pointed to by index
  57. *)
  58. PROCEDURE GetIndRect(ID: Integer; index: Integer; VAR targetRect: Rect);
  59. VAR     resHandle: RectsRecHandle;
  60.         theRects: Ptr;
  61.         limit: Integer;
  62.         r : Rect;
  63.         
  64.     BEGIN
  65.         resHandle := RectsRecHandle(GetResource('RCT#', ID));
  66.         IF ((resHandle <> NIL) AND (resHandle^^.rectCount >= index)) THEN
  67.           BEGIN
  68.             targetRect := resHandle^^.rects[index];
  69.           END
  70.         ELSE
  71.           SetRect(targetRect, 0, 0, 0, 0); (* empty rect signals failure *)
  72.     END;
  73.  
  74.  
  75. (* Handy little routine used to display values in hex *)
  76. procedure NumToHex (n: Longint; w: Integer; var s: Str255);
  77.     const
  78.         hex = '0123456789ABCDEF';
  79.     var
  80.         i: Integer;
  81. begin
  82.     s := '$00000000';
  83.     for i := 0 to w - 1 do
  84.         begin
  85.             s[9 - i] := hex[BitAnd(n, $0000000F) + 1];
  86.             n := BitShift(n, -4);
  87.         end;
  88. end;
  89.  
  90. PROCEDURE ErrorControl(message: Str255);
  91.  
  92. BEGIN
  93.     DebugStr(message);
  94. END;
  95.  
  96. (* Display state values from Time base state record *)
  97. PROCEDURE DrawContents;
  98. VAR        r: Rect;
  99.         where: Point;
  100.         s, s2: STR255;
  101.         aFix: Fixed;
  102.         fNum: Integer;
  103.         sysFont: Str255;
  104.         startTimeValue,
  105.         stopTimeValue : TimeValue;
  106.         startTime, stopTime: TimeRecord;
  107.         
  108. BEGIN
  109.     GetFNum('Courier', fNum); (* want to set our font        *)
  110.     
  111.     IF fNum <> 0 THEN         (* but only when available     *)
  112.         TextFont(fNum)
  113.     ELSE (* make sure that 0 is the correct result IM VI 12-16 *)
  114.       BEGIN
  115.         GetFontName(0, sysFont);
  116.         IF EqualString('Courier', sysFont, FALSE, FALSE) THEN
  117.           TextFont(fNum)
  118.       END;
  119.  
  120.     (* Display movie duration *)
  121.  
  122.     (* All the strings are postioned
  123.        using rectangles that are kept in a RCT# resource.
  124.     *)
  125.     GetIndRect(rRCTID, 0, r);
  126.     MoveTo(r.left, r.bottom - 3);
  127.     DrawString('Duration = ');
  128.  
  129.     NumToString(gTBState.duration, s);
  130.     GetIndRect(rRCTID, 1, r);
  131.     MoveTo(r.right - (StringWidth(s) + 2), r.bottom - 3);
  132.  
  133.     EraseRect(r);
  134.     FrameRect(r);
  135.     DrawString(s);
  136.  
  137.     NumToString(gTBState.moovScale, s);
  138.     s := Concat(' 1/',s);
  139.     GetIndRect(rRCTID, 2, r);
  140.     MoveTo(r.right - (StringWidth(s) + 2), r.bottom - 3);
  141.     EraseRect(r);
  142.     FrameRect(r);
  143.     DrawString(s);
  144.     Move(2,0);
  145.     DrawString('th. sec.');          
  146.  
  147.     (* Display movie rate information *)
  148.  
  149.     GetIndRect(rRCTID, 3, r);
  150.     MoveTo(r.left, r.bottom - 3);
  151.     DrawString('Rate Settings');
  152.  
  153.     GetIndRect(rRCTID, 4, r);
  154.     MoveTo(r.left, r.bottom - 3);
  155.     DrawString('Current = ');
  156.  
  157.     GetIndRect(rRCTID, 5, r);
  158.     NumToHex(gTBState.rate,8, s);
  159.     MoveTo(r.right - (StringWidth(s) + 2), r.bottom - 3);
  160.  
  161.     EraseRect(r);
  162.     FrameRect(r);
  163.     DrawString(s);
  164.  
  165.     GetIndRect(rRCTID, 6, r);
  166.     MoveTo(r.left, r.bottom - 3);
  167.     DrawString('Preferred = ');
  168.  
  169.     GetIndRect(rRCTID, 7, r);
  170.     aFix := GetMoviePreferredRate(gMoov);
  171.     NumToHex(aFix,8, s);
  172.     MoveTo(r.right - (StringWidth(s) + 2), r.bottom - 3);
  173.  
  174.     EraseRect(r);
  175.     FrameRect(r);
  176.     DrawString(s);
  177.     
  178.     (* display clock name *)
  179.     
  180.     GetIndRect(rRCTID, 8, r);
  181.     MoveTo(r.left, r.bottom - 3);
  182.     s := Concat('ClockName = ',gTBState.clockName);
  183.     DrawString(s);
  184.     
  185.     (* Display start and stop values *)
  186.     
  187.     startTimeValue := GetTimeBaseStartTime(gTBState.tBase, gTBState.moovScale, startTime);
  188.     stopTimeValue := GetTimeBaseStopTime(gTBState.tBase, gTBState.moovScale, stopTime);
  189.  
  190.     GetIndRect(rRCTID, 9, r);
  191.     MoveTo(r.left, r.bottom - 3);
  192.     DrawString('Start    = ');
  193.  
  194.     NumToString(startTimeValue, s);
  195.     GetIndRect(rRCTID, 10, r);
  196.     MoveTo(r.right - (StringWidth(s) + 2), r.bottom - 3);
  197.  
  198.     EraseRect(r);
  199.     FrameRect(r);
  200.     DrawString(s);
  201.  
  202.     GetIndRect(rRCTID, 11, r);
  203.     MoveTo(r.left, r.bottom - 3);
  204.     DrawString('Stop     = ');
  205.  
  206.     NumToString(stopTimeValue, s);
  207.     GetIndRect(rRCTID, 12, r);
  208.     MoveTo(r.right - (StringWidth(s) + 2), r.bottom - 3);
  209.  
  210.     EraseRect(r);
  211.     FrameRect(r);
  212.     DrawString(s);
  213.  
  214. END;
  215.  
  216. (* boolean parameter tells if we have to erase and frame or just redraw the string *)
  217. PROCEDURE DrawShuttleValue(doAll: Boolean);
  218. VAR        valueS:        Str255;
  219.         theRect:    Rect;
  220.         tb: TimeBase;
  221.         outTime: TimeRecord;
  222.         tv: TimeValue;
  223.         value:    Integer;
  224. BEGIN
  225.     theRect := gShuttle^^.contrlRect;
  226.     value := gShuttle^^.contrlValue;
  227.     InsetRect(theRect, 28,32);
  228.     EraseRect(theRect);
  229.     InsetRect(theRect, 1, 1);
  230.     IF doAll THEN
  231.       FrameRect(theRect);
  232.     MoveTo(theRect.left+2, theRect.bottom-4);
  233.     NumToString(value, valueS);
  234.     InsetRect(theRect, 1, 1);
  235.     DrawString(valueS);
  236. END;
  237. {
  238. Shuttle button calls this proc when tracking so that I can update the value. It also gets
  239. called when SetCtrlValue is called.
  240. }
  241. PROCEDURE TrackingActionProc;
  242. VAR        value:    Integer;
  243.         
  244. BEGIN
  245.  
  246.     DrawShuttleValue(FALSE);
  247.     
  248.     (* The shuttle control allows to scan the movie forward or backward
  249.        one ' movie scale/10' tick at the time.
  250.     *)
  251.  
  252.     SetTimeBaseValue(gTBState.tBase, value*10, gTBState.moovScale);
  253.     MoviesTask(gMoov, doTheRightThing); (* let the movie move during long trackings *)
  254. END;
  255.  
  256. PROCEDURE HandleGoAway(WPtr : WindowPtr; MLoc : Point);
  257. {
  258.     purpose         handle mouse click in go-away box
  259. }
  260. VAR
  261.   WPeek             : WindowPeek;           { for looking at windows    }
  262. BEGIN
  263.   IF WPtr = FrontWindow THEN                  { if it's the active window }
  264.     BEGIN
  265.       WPeek := WindowPeek(WPtr);            { peek at the window        }
  266.       IF TrackGoAway(WPtr,MLoc) THEN        {   and the box is clicked  } 
  267.         IF WPeek^.WindowKind = userKind THEN{     if it's our window    }   
  268.           gDoneFlag := True                   {       then time to stop   }
  269.     END   
  270.   ELSE 
  271.     SelectWindow(WPtr)                       { else make it active       }
  272. END; { of proc HandleGoAway }
  273.  
  274. (* Given a window and a control returns the id of the control.
  275.    Note that this works only because I know the order in which controls are added
  276.    in and also that controls are not deleted.
  277.    If result is -1 then we don't know what control is it.
  278.    Controls get attached firs come first served, so the list is
  279.    last first.
  280. *)
  281. FUNCTION GetControlID(whichControl: ControlHandle; wind: WindowPtr): Integer;
  282. VAR    nextCon: ControlHandle;
  283.     count: Integer;
  284.     
  285. BEGIN
  286.     nextCon := WindowPeek(wind)^.controlList;
  287.     count := lastControl;                (* last control *)
  288.  
  289.     WHILE whichControl <> nextCon DO
  290.       BEGIN
  291.         nextCon := nextCon^^.nextControl;
  292.         IF nextCon = NIL THEN
  293.           BEGIN
  294.             count := -1;
  295.             LEAVE
  296.           END
  297.         ELSE
  298.           count := count-1;
  299.       END;
  300.     GetControlID := count;
  301. END;
  302.  
  303. (* Returns the control handle given an controlID *)
  304. (* Controls are put in the list in last in first in list order *)
  305. FUNCTION GetControlFromID(id: Integer;wind: WindowPtr): ControlHandle;
  306. VAR    nextCon: ControlHandle;
  307.     count: Integer;
  308.  
  309. BEGIN
  310.     nextCon := WindowPeek(wind)^.controlList;
  311.     FOR count := 1 TO lastControl - id DO
  312.       BEGIN
  313.           nextCon := nextCon^^.nextControl;
  314.         IF nextCon = NIL THEN LEAVE
  315.       END;
  316.     GetControlFromID := nextCon;
  317. END;
  318.  
  319. PROCEDURE SetLoop( id: INTEGER);
  320. VAR     controlH: ControlHandle;
  321.  
  322. BEGIN
  323.     CASE id OF
  324.       129:
  325.           BEGIN
  326.             controlH := GetControlFromID(129, gWind);
  327.             IF GetCtlValue(controlH) = 0 THEN (* loop is on *)
  328.               BEGIN
  329.                 SetTBLoop(0); (* no loop *)
  330.                 SetCtlValue(controlH, 1);
  331.                 controlH := GetControlFromID(130, gWind);
  332.                 SetCtlValue(controlH, 0);
  333.                 controlH := GetControlFromID(131, gWind);
  334.                 SetCtlValue(controlH, 0);
  335.               END
  336.           END;
  337.       130:
  338.           BEGIN
  339.             controlH := GetControlFromID(130, gWind);
  340.             IF GetCtlValue(controlH) = 0 THEN 
  341.               BEGIN
  342.                 SetTBLoop(loopTimeBase); (* normal loop *)
  343.                 SetCtlValue(controlH, 1);
  344.                 controlH := GetControlFromID(129, gWind);
  345.                 SetCtlValue(controlH, 0);
  346.                 controlH := GetControlFromID(131, gWind);
  347.                 SetCtlValue(controlH, 0);
  348.               END
  349.           END;
  350.       131:
  351.           BEGIN
  352.             controlH := GetControlFromID(131, gWind);
  353.             IF GetCtlValue(controlH) = 0 THEN 
  354.               BEGIN
  355.                 SetTBLoop(palindromeLoopTimeBase); (* palindrome loop *)
  356.                 SetCtlValue(controlH, 1);
  357.                 controlH := GetControlFromID(129, gWind);
  358.                 SetCtlValue(controlH, 0);
  359.                 controlH := GetControlFromID(130, gWind);
  360.                 SetCtlValue(controlH, 0);
  361.               END
  362.           END;
  363.     END
  364. END;
  365.  
  366. PROCEDURE CallSetCtlValueNoProc(shuttle: ControlHandle; newValue: Integer);
  367. BEGIN
  368.     IF shuttle^^.contrlValue <> newValue THEN
  369.       BEGIN
  370.         SetCRefCon(gShuttle, 0); (* make sure my tracking is not called *)
  371.     
  372.         SetCtlValue(shuttle, newValue);
  373.         
  374.         SetCRefCon(gShuttle, LongInt(@TrackingActionProc));
  375.         
  376.         DrawShuttleValue(FALSE);
  377.       END
  378. END;
  379.  
  380. PROCEDURE InitControls(moov: Movie; wind: WindowPtr);
  381. VAR     controlH: ControlHandle;
  382.         value:    Integer;
  383.         TBFlags: LONGINT;
  384.         rate:    Fixed;
  385.  
  386. FUNCTION ShuttleDuration: TimeValue;
  387. (* the movie duration is given in 'normal' movie rate units, this makes advancing the
  388.    movie using the shuttle control a little too much work, so for the control we keep
  389.    the duration at a coarser rate. We take the movie rate and convert it to its 1/10th.
  390.    so if the movie rate is 600 (meaning 600 time units persecond or about 60 time units
  391.    per video frame) the controller 'rate' is 60 or 6 of its units per video frame. This
  392.    produces the effect of being able to scroll through the movie without having to go
  393.    round and round and round and …
  394. *)
  395.     VAR        tr: TimeRecord;
  396.             localDuration: TimeValue;
  397.             shuttleScale : TimeScale;
  398.     BEGIN
  399.       WITH gTBState DO
  400.         BEGIN
  401.             shuttleScale := moovScale DIV 10;
  402.           localDuration := GetTimeBaseStopTime(tBase, shuttleScale, tr);
  403.           localDuration := localDuration - GetTimeBaseStartTime(tBase, shuttleScale, tr);
  404.         END;
  405.       ShuttleDuration := localDuration;
  406.     END;
  407.  
  408. BEGIN
  409.     InitTBRecord(moov);
  410.  
  411.     SetCRefCon(gShuttle, 0); (* make sure my tracking is not called *)
  412.     SetCtlMax(gShuttle, ShuttleDuration);
  413.     SetCtlMin(gShuttle,0);
  414.     SetCtlValue(gShuttle, 0);
  415.     
  416.     SetCRefCon(gShuttle, LongInt(@TrackingActionProc));
  417.  
  418.     TBFlags := gTBState.flags;
  419.     CASE TBFlags OF
  420.       0:
  421.           BEGIN
  422.             controlH := GetControlFromID(129, gWind);
  423.             SetCtlValue(controlH, 1);
  424.             controlH := GetControlFromID(130, gWind);
  425.             SetCtlValue(controlH, 0);
  426.             controlH := GetControlFromID(131, gWind);
  427.             SetCtlValue(controlH, 0);
  428.           END;
  429.       1:
  430.           BEGIN
  431.             controlH := GetControlFromID(130, gWind);
  432.             SetCtlValue(controlH, 1);
  433.             controlH := GetControlFromID(129, gWind);
  434.             SetCtlValue(controlH, 0);
  435.             controlH := GetControlFromID(131, gWind);
  436.             SetCtlValue(controlH, 0);
  437.           END;
  438.       2:
  439.           BEGIN
  440.             controlH := GetControlFromID(131, gWind);
  441.             SetCtlValue(controlH, 1);
  442.             controlH := GetControlFromID(129, gWind);
  443.             SetCtlValue(controlH, 0);
  444.             controlH := GetControlFromID(130, gWind);
  445.             SetCtlValue(controlH, 0);
  446.           END;
  447.     END; (* CASE *)
  448.     
  449.     (* init set preferred rate button *)
  450.     controlH := GetControlFromID(132, gWind);
  451.     HiliteControl(controlH, 255);    (* disable until there is something to do *)
  452.     rate := GetMoviePreferredRate(gMoov); 
  453.     SetCRefCon(controlH, rate); 
  454.  
  455.     (* init reset preferred rate button *)
  456.     controlH := GetControlFromID(133, gWind);
  457.     rate := GetMoviePreferredRate(gMoov); 
  458.     SetCRefCon(controlH, rate); 
  459.  
  460. END;
  461.  
  462.  
  463. FUNCTION InArrows(loc: Point): BOOLEAN;
  464.  
  465. BEGIN
  466.     InArrows := PtInRect(loc, gArrows^^.picFrame);
  467. END;
  468.  
  469. (* the user clicked on set rate so we go ahead and change the preferred rate *)
  470. PROCEDURE SetPreferredRate(id: Integer);
  471. VAR    controlH:        ControlHandle;
  472.     new:             Fixed;
  473.     err:             OSerr;
  474.     
  475. BEGIN
  476.     controlH := GetControlFromID(id, gWind);
  477.     new := GetCRefCon(controlH);
  478.     SetMoviePreferredRate(gMoov, new);
  479.     err := GetMoviesError;
  480.     IF err <> noErr THEN
  481.       DebugStr('Could not set the movie rate');
  482.     err := MCMovieChanged(gMCPlay, gMoov); (* let the controller know of the change *)
  483.     HiliteControl(controlH, 255); (* we did set the rate, now disable *)
  484. END;
  485.  
  486. (* we use the control refcon to keep the preferred rate, and we set it
  487.    if the user clicks on the set button.
  488. *)
  489. PROCEDURE SetRefConRate(new: Fixed);
  490. VAR    controlH:        ControlHandle;
  491.     old: Fixed;
  492.     
  493. BEGIN
  494.     controlH := GetControlFromID(132, gWind);
  495.     old := GetCRefCon(controlH);
  496.     IF new <> old THEN
  497.       BEGIN
  498.         HiliteControl(controlH, 0);    (* enable to allow change *)
  499.         SetCRefCon(controlH, new);
  500.       END;
  501. END;
  502.  
  503. (* the user clicked on reset rate; put preferred rate to the value the movie came
  504.    with from the file *)
  505. PROCEDURE ResetPreferredRate(id: Integer);
  506. VAR    controlH:        ControlHandle;
  507.     enteredPrefRate,
  508.     rateFromFile:    Fixed;
  509.     err:             OSerr;
  510.     r:                Rect;
  511.     
  512. BEGIN
  513.     controlH := GetControlFromID(id, gWind);
  514.     rateFromFile := GetCRefCon(controlH);
  515.     controlH := GetControlFromID(id - 1, gWind); (* if I am here, then the previous control *)
  516.  
  517.     SetMoviePreferredRate(gMoov, rateFromFile);
  518.     err := MCMovieChanged(gMCPlay, gMoov);
  519.     GetIndRect(rRCTID, 7, r);
  520.     InvalRect(r);
  521.     HiliteControl(controlH, 255);    (* enable to allow change *)
  522.     SetCRefCon(controlH, rateFromFile);
  523. END;
  524.  
  525. (* When the user clicks on the arrows the selected rate decreases or increases
  526.    through this function.
  527. *)
  528. PROCEDURE TrackArrows(loc: Point);
  529. VAR    thePoint:    Point;
  530.     inUp,
  531.     inDown:        BOOLEAN;
  532.     middle:        Integer;
  533.     topRect,
  534.     bottomRect:    Rect;
  535.     upRgn, rRgn,
  536.     downRgn:    RgnHandle;
  537.     poly:        PolyHandle;
  538.     rate:        Fixed;
  539.     
  540. PROCEDURE DrawRate;
  541.     VAR    r:    Rect;
  542.         where: Point;
  543.         s: Str255;
  544.         
  545.     BEGIN
  546.       GetIndRect(rRCTID, 7, r);
  547.       NumToHex(rate,8, s);
  548.       MoveTo(r.right - (StringWidth(s) + 2), r.bottom - 3);
  549.  
  550.       InsetRect(r,1,1);
  551.       TextMode(srcCopy);
  552.       DrawString(s);
  553.     END;
  554.     
  555. BEGIN
  556.     upRgn := NewRgn;
  557.     downRgn := NewRgn;    
  558.     rRgn := NewRgn;
  559.     rate := GetCRefCon(GetControlFromID(132, gWind)); (* since we declare it, use it *)
  560.     
  561.     (* rather ugly way to get the correct shape for the arrows, it works though! *)
  562.     topRect := gArrows^^.picFrame;
  563.     OffsetRect(topRect,-1,-1);
  564.     WITH topRect DO
  565.       BEGIN
  566.       OpenRgn;
  567.         MoveTo(left+3,top+2);
  568.         LineTo(right-2,top+2); 
  569.         LineTo(right, top+4);  
  570.         LineTo(right, bottom-2);
  571.         LineTo(right-2,bottom);
  572.         LineTo(left+3,bottom);
  573.         LineTo(left+2,bottom-1);
  574.         LineTo(left+2,top+4);
  575.         LineTo(left+3,top+2);
  576.       CloseRgn(rRgn);
  577.       END;
  578.       
  579.     inUp:= FALSE;
  580.     inDown:=FALSE;
  581.     middle := (gArrows^^.picFrame.bottom-gArrows^^.picFrame.top) DIV 2;
  582.  
  583.     topRect := gArrows^^.picFrame;
  584.     topRect.bottom := topRect.bottom - middle;
  585.     bottomRect := gArrows^^.picFrame;
  586.     bottomRect.top := bottomRect.top + middle;
  587.  
  588.     middle := bottomRect.top;
  589.     RectRgn(upRgn, topRect);
  590.     SectRgn(upRgn, rRgn, upRgn);
  591.     RectRgn(downRgn, bottomRect);
  592.     SectRgn(downRgn, rRgn, downRgn);
  593.     
  594.     REPEAT
  595.       BEGIN
  596.         GetMouse(thePoint);
  597.         IF PtInRect(thePoint, gArrows^^.picFrame) THEN
  598.           BEGIN
  599.             IF thePoint.v < middle THEN (* mouse on top part *)
  600.               BEGIN
  601.                 rate := rate + $00000010;
  602.                 DrawRate;
  603.                 IF inDown THEN
  604.                   BEGIN
  605.                     InvertRgn(downRgn); (* un hilite down arrow *)
  606.                     InvertRgn(upRgn);    (* hilite up            *)
  607.                     inDown := FALSE;
  608.                   END
  609.                 ELSE        (* in up arrow again *)
  610.                   BEGIN
  611.                     IF NOT inUp THEN (* first time hilite the arrow *)
  612.                       InvertRgn(upRgn);    (* hilite up            *)
  613.                   END;
  614.                 inUp := TRUE
  615.               END
  616.             ELSE    (* cursor is on top of down arrow *)
  617.               BEGIN
  618.                 rate := rate + $FFFFFFF0;
  619.                 DrawRate;
  620.                 IF inUp THEN
  621.                   BEGIN
  622.                     InvertRgn(downRgn); (* un hilite down arrow *)
  623.                     InvertRgn(upRgn);    (* hilite up            *)
  624.                     inUp := FALSE;
  625.                   END
  626.                 ELSE        (* in up arrow again *)
  627.                   BEGIN
  628.                     IF NOT inDown THEN
  629.                       InvertRgn(downRgn);
  630.                   END;
  631.                 inDown := TRUE
  632.               END
  633.           END
  634.         ELSE
  635.           BEGIN
  636.             IF inUp THEN
  637.               BEGIN
  638.                 inUp := FALSE;
  639.                 InvertRgn(upRgn);
  640.               END;
  641.             IF inDown THEN
  642.               BEGIN
  643.                 inDown := FALSE;
  644.                 InvertRgn(downRgn);
  645.               END;
  646.           END;
  647.       END
  648.     UNTIL NOT StillDown;
  649.  
  650.     IF inUp THEN (* clean things up before leaving *)
  651.       BEGIN
  652.         InvertRgn(upRgn);
  653.       END;
  654.     IF inDown THEN
  655.       BEGIN
  656.         InvertRgn(downRgn);
  657.       END;
  658.  
  659.     SetRefConRate(rate); (* if it has chaged will store new value *)
  660.  
  661.     DisposeRgn(upRgn);
  662.     DisposeRgn(downRgn);    
  663.     DisposeRgn(rRgn);
  664.     TextMode(srcOr);
  665. END;
  666.  
  667.  
  668. PROCEDURE DoContent(VAR where: Point; what: WindowPtr);
  669. VAR            whichControl: ControlHandle;
  670.             controlID: Integer;
  671.  
  672. BEGIN
  673.     GlobalToLocal(where);
  674.     IF ( FindControl(where, what, whichControl) <> 0 ) THEN
  675.       BEGIN
  676.         controlID := GetControlID(whichControl, what);
  677.         IF ( TrackControl(whichControl, where, ProcPtr(-1)) <> 0) THEN
  678.           BEGIN
  679.             CASE controlID OF
  680.             128:;
  681.             129:SetLoop( controlID);
  682.             130:SetLoop( controlID);
  683.             131:SetLoop( controlID);
  684.             132:SetPreferredRate( controlID);
  685.             133:ResetPreferredRate( controlID);
  686.             OTHERWISE
  687.             DebugStr('Bummer: could not find the control');
  688.             END
  689.           END
  690.       END
  691.     ELSE
  692.       IF InArrows(where) THEN
  693.         TrackArrows(where);
  694. END;
  695.  
  696. PROCEDURE DoMouseDown(theEvent:EventRecord);
  697.     purpose         identify where mouse was clicked and handle it
  698. }
  699. VAR
  700.   Location      : Integer;
  701.   theWindow     :    WindowPtr;
  702.   MLoc          :    Point;
  703.   WLoc          :    Integer;
  704.    
  705. BEGIN
  706.   MLoc  := theEvent.Where;              { get mouse position            }
  707.   WLoc := FindWindow(MLoc,theWindow);   { get window, loc in window     }
  708.   CASE WLoc OF                          { handle window locations       }
  709.     InGoAway    : HandleGoAway(theWindow,MLoc);     { in the go away box}
  710.     InContent:      DoContent(MLoc, theWindow);
  711.     OTHERWISE     ;
  712.   END;
  713. END; { of proc DoMouseDown }
  714.  
  715. PROCEDURE UpdateStuff(what: WindowPtr);
  716.  
  717. BEGIN
  718.     BeginUpdate(what);
  719.       SetPort(what);
  720.       DrawPicture(gArrows, gArrows^^.picFrame);
  721.       DrawControls(what);
  722.       DrawShuttleValue(TRUE);                     
  723.       DrawContents;
  724.     EndUpdate(what);
  725. END;
  726.  
  727. PROCEDURE HandleEvent(theEvent : EventRecord);
  728.     purpose         decodes event and handles it
  729. }
  730. BEGIN
  731.   CASE theEvent.What OF
  732.     mouseDown       : DoMouseDown(theEvent);      { mouse button pushed   }
  733.     updateEvt:         UpdateStuff(WindowPtr(theEvent.message));
  734.   END
  735. END; { of proc HandleEvent }
  736.  
  737. PROCEDURE InitVars;
  738. BEGIN
  739. { Initialization of variables used for time base samples }
  740.   gDoneFlag := FALSE;        { to begin with                        }
  741.   gLooping := FALSE;
  742. END;
  743.  
  744. FUNCTION InitSystem: OSErr;
  745.     purpose         initialize everything for the program
  746.                     returns an error if QuickTIme is not present or
  747.                     if EnterMovies failed.
  748. }
  749. VAR
  750.   result:     OSErr;
  751.   arrow:    PicHandle;
  752.  
  753. FUNCTION GetGestaltResult(gestaltSelector: OSType):Integer;
  754. VAR
  755.   result : LONGINT;
  756.   
  757. BEGIN
  758.   IF Gestalt(gestaltSelector, result) = noErr THEN
  759.     GetGestaltResult := result
  760.   ELSE
  761.     GetGestaltResult := 0;
  762. END;
  763.  
  764. BEGIN
  765.  
  766.   MaxApplZone;
  767.   
  768.   { initialize all the different managers                               }
  769.   InitGraf(@thePort);               { create a grafport for the screen  }
  770.   InitFonts;                        { start up the font manager         }
  771.   InitWindows;                      { start up the window manager       }
  772.   InitMenus;                        { start up the menu manager         }
  773.   TEInit;                           { start up the text manager for DAs }
  774.   InitDialogs(NIL);                 { start up the dialog manager       }
  775.   FlushEvents(everyEvent,0);        { clear events from previous state  }
  776.   
  777.   WITH gMoovBox DO        { Use this routine to init the window rect }
  778.     BEGIN
  779.       top:= 10;
  780.       left:= 300;
  781.       bottom := 190;
  782.       right := 480;
  783.     END;
  784.     
  785.   arrow := PicHandle(GetResource('PICT', arrowsID));
  786.   IF arrow <> NIL THEN
  787.     BEGIN
  788.       DetachResource(Handle(arrow));
  789.       gArrows := arrow;
  790.     END
  791.   ELSE
  792.     gArrows := NIL;
  793.   InitVars;        { to begin with                        }
  794.  
  795.   gSystemVersion := GetGestaltResult (gestaltSystemVersion);
  796.   
  797.   IF GetGestaltResult(gestaltQuickTime) <> 0 THEN { zero means no such selector }
  798.     result:= EnterMovies
  799.   ELSE
  800.     result := movieToolboxUnitialized;
  801.   InitSystem := result;
  802.   
  803. END; (* InitSystem *)
  804.  
  805. PROCEDURE ConvertOldToNew(oldSF: SFReply; VAR newSF: StandardFileReply);
  806.     purpose         converts an old style SFReply inot a system 7
  807.                     StandardFileReply.
  808. }
  809. VAR        err:            OSErr;
  810.         ignoreProc:        LONGINT;
  811.         
  812. BEGIN
  813.       WITH newSF, oldSF DO
  814.       BEGIN
  815.         sfGood := good;
  816.         sfReplacing := copy;
  817.         sfType := fType;
  818.         err := FSMakeFSSpec(vRefNum, 0, fName, sfFile);
  819.         sfScript := iuSystemScript;
  820.         sfFlags := 0;
  821.         sfIsFolder := false;
  822.         sfIsVolume := false;
  823.         sfReserved1 := 0;
  824.         sfReserved2 := 0;
  825.       END;
  826. END;
  827.  
  828. FUNCTION DisplayGetFile(prompt: Str255; VAR reply: StandardFileReply): BOOLEAN;
  829.     purpose         promp the user to select a file works in both system 6 and 7.
  830. }
  831. VAR        fileTypes:        SFTypeList;
  832.         localReply:        SFReply;
  833.         where:            Point;
  834.         err:            OSerr;
  835. BEGIN
  836.     where.h:=100;
  837.     where.v:=100;
  838.     fileTypes[0]:='MooV';
  839.     
  840.     IF gSystemVersion >= $0700 THEN     { new standard file available }
  841.       StandardGetFilePreview(nil, 1, fileTypes, reply)    
  842.     ELSE
  843.       BEGIN
  844.         SFGetFIle(where, prompt, nil, 1, fileTypes, nil, localReply);
  845.         ConvertOldToNew(localReply, reply);
  846.       END;
  847.     DisplayGetFile := reply.sfGood;
  848. END;
  849.  
  850. (******* END Auxiliary routines ********************************************************)
  851.  
  852.